package pos;

import pos.utils.Pickable;
import com.sun.j3d.utils.pickfast.PickCanvas;
import java.awt.AWTEvent;
import java.awt.event.*;
import java.util.Enumeration;
import javax.media.j3d.*;
import javax.vecmath.Point3d;

/**
 * 主菜单模式的AWT事件行为
 * @author plus
 */
public class EventBehavior extends Behavior {

    private WakeupOnAWTEvent AWTMouseEventCondition;
    private WakeupOnAWTEvent AWTKeyEventCondition;
    private WakeupOr AWTBothEventCondition;
    private BranchGroup BGTarget,  BGSaved;
    private PickCanvas Picker;
    private IModeController Controller,  ControllerSaved;

    /**
     * 构造函数，构造后需加入场景树中才生效
     * @param BGTarg 需要对象拾取的子场景图
     * @param Controller 当前模式控制器
     */
    EventBehavior(BranchGroup BGTarg, IModeController Controller) {
        this.setSchedulingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 15000));

        AWTMouseEventCondition = new WakeupOnAWTEvent(AWTEvent.MOUSE_EVENT_MASK |
                AWTEvent.MOUSE_MOTION_EVENT_MASK);
        AWTKeyEventCondition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
        AWTBothEventCondition = new WakeupOr(
                new WakeupCriterion[]{AWTMouseEventCondition, AWTKeyEventCondition});

        this.setTarget(BGTarget, Controller);

    }

    /**
     * 初始化行为，仅允许java3d行为控制器调用
     */
    public void initialize() {
        this.wakeupOn(AWTBothEventCondition);
    }

    /**
     * 发生行为，仅允许java3d行为控制器调用
     * @param criteria 出发行为的条件序列
     */
    public void processStimulus(Enumeration criteria) {
        //if (this.BGTarget!=null && this.Controller!=null)
        while (criteria.hasMoreElements()) {
            WakeupCriterion currentCriterion = (WakeupCriterion) criteria.nextElement();
            if (currentCriterion.equals(AWTMouseEventCondition)) {
                AWTEvent[] event = AWTMouseEventCondition.getAWTEvent();
                for (int i = 0; i < event.length; i++) {
                    Pickable pickRes = pick((MouseEvent) event[i]);
                    if (pickRes != null) {
                        pickRes.picked((MouseEvent) event[i]);
                    }
                }
            } else if (currentCriterion.equals(AWTKeyEventCondition)) {
                AWTEvent[] event = AWTKeyEventCondition.getAWTEvent();
                for (int i = 0; i < event.length; i++) {
                    this.Controller.doEvent("KeyEvent", event[i]);
                }
            }
        }
        this.wakeupOn(AWTBothEventCondition);
    }

    public void setTarget(BranchGroup BGTarget, IModeController Controller) {
        this.BGTarget = BGTarget;
        this.Controller = Controller;
        if (this.BGTarget != null && this.Controller != null) {
            System.err.println(BGTarget);
            Picker = new PickCanvas(ControlCenter.canvas, BGTarget);
            Picker.setMode(PickInfo.PICK_GEOMETRY);
            Picker.setFlags(PickInfo.CLOSEST_INTERSECTION_POINT | PickInfo.NODE);
            Picker.setTolerance(0.0f);
        }
    }

    public void pushTarget(BranchGroup BGTarget, IModeController Controller) {
        BGSaved = this.BGTarget;
        ControllerSaved = this.Controller;
        this.BGTarget = BGTarget;
        this.Controller = Controller;
        if (this.BGTarget != null && this.Controller != null) {
            System.err.println(BGTarget);
            Picker = new PickCanvas(ControlCenter.canvas, BGTarget);
            Picker.setMode(PickInfo.PICK_GEOMETRY);
            Picker.setFlags(PickInfo.CLOSEST_INTERSECTION_POINT | PickInfo.NODE);
            Picker.setTolerance(0.0f);
        }
    }

    public void popTarget() {
        this.setTarget(BGSaved, ControllerSaved);
    }

    private Pickable pick(MouseEvent event) {
        Picker.setShapeLocation(event);
        if (Picker.getBranchGroup().isLive()) {
            PickInfo pickRes = Picker.pickClosest();
            if (pickRes != null) {
                if (pickRes.getNode() instanceof Pickable) {
                    return (Pickable) pickRes.getNode();
                } else if (pickRes.getNode().getParent() instanceof Pickable) {
                    return (Pickable) pickRes.getNode().getParent();
                } else {
                    return null;
                }
            } else {
                return null;
            }
        }
        return null;
    }
}
